package org.zhang.core.asm;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.zhang.core.config.ProfilingFilter;

import static org.objectweb.asm.Opcodes.*;
import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;

public class MethodInterceptorClassVisitor extends ClassVisitor {
    private String className;
    private boolean isInterface;
    private boolean isServletClass = false;

    public MethodInterceptorClassVisitor(int api, ClassVisitor classVisitor, String className) {
        super(api, classVisitor);
        this.className = className.replace('/', '.'); // 将内部类名格式转换为普通的点分隔格式
        if ("javax.servlet.http.HttpServlet".equals(this.className)) {
            System.out.println("servlet:" + this.className);
            isServletClass = true;
        }
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
        this.isInterface = (access & ACC_INTERFACE) != 0;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = cv.visitMethod(access, name, descriptor, signature, exceptions);
        // 不对接口和私有方法注入
        if (isInterface || (access & ACC_PRIVATE) != 0) {
            return mv;
        }
        //不对抽象方法、native方法、桥接方法、合成方法进行注入
        if ((access & ACC_ABSTRACT) != 0
                || (access & ACC_NATIVE) != 0
                || (access & ACC_BRIDGE) != 0
                || (access & ACC_SYNTHETIC) != 0) {
            return mv;
        }
        // 只处理非构造方法
        if ("<init>".equals(name) || "<clinit>".equals(name)) {
            return mv;
        }
        boolean isServiceMethod = false;
        if (isServletClass) {
            //如果是servlet类，只插桩service请求方法
            if ("service".equals(name)) {
                isServiceMethod = true;
                System.out.println("发起请求的方法：" + className + "--" + name);
            } else {
                return mv;
            }
        }
        // 过滤Object类默认方法
        if (ProfilingFilter.isNotNeedInjectMethod(name)) {
            return mv;
        }
        return new MethodInterceptorMethodVisitor(api, mv, access, name, descriptor, className, isServiceMethod);
    }
}